<template>
  <div class="tts-container">
    <div class="container">
      <div class="content">
        <div class="main-content">
          <!-- 左侧区域 -->
          <div class="left-section">
            <div class="input-section">
              <div class="header">
                <h1 class="title">个性语音讲解</h1>
                <a-tooltip title="选择文本输入或上传文件进行语音合成">
                  <QuestionCircleOutlined class="help-icon" />
                </a-tooltip>
              </div>
              <div class="input-type-buttons">
                <a-button :class="{ 'active': inputType === 'text' }" class="input-button"
                  @click="setInputType('text')">文本输入</a-button>
                <a-button :class="{ 'active': inputType === 'file' }" class="input-button"
                  @click="setInputType('file')">上传文件</a-button>
              </div>
              <div v-if="inputType === 'text'" class="text-input-wrapper">
                <a-textarea v-model:value="inputText" placeholder="请输入要转换的文本内容..." class="text-area"
                  :disabled="isGenerating" />
                <div class="text-counter">
                  {{ inputText.length }} / 5000
                </div>
              </div>
              <div v-else class="file-upload-section" :class="{ 'disabled': isGenerating }" @click="handleFileClick"
                @drop.prevent="handleFileDrop" @dragover.prevent="!isGenerating" @dragenter.prevent="!isGenerating">
                <input type="file" ref="fileInput" style="display: none" @change="handleFileSelect" accept=".txt"
                  :disabled="isGenerating" />
                <template v-if="!uploadedFile">
                  <upload-outlined class="upload-icon" />
                  <p class="upload-text">点击或拖拽文件到此处上传</p>
                  <p class="upload-hint">支持 .txt 格式，文件大小不超过10MB</p>
                </template>
                <div v-if="uploadedFile" class="uploaded-file-info">
                  <div class="file-info-header">
                    <FileTextOutlined class="file-icon" />
                    <span class="file-name">{{ uploadedFile.name }}</span>
                  </div>
                  <div class="file-details">
                    <span class="file-size">{{ formatFileSize(uploadedFile.size) }}</span>
                  </div>
                </div>
              </div>
              <div class="generate-button-wrapper">
                <a-button type="primary" class="generate-button" :class="{ 'disabled-button': !canGenerate }"
                  :disabled="!canGenerate" @click="handleGenerate" :loading="isGenerating">
                  生成语音
                </a-button>
              </div>
            </div>
          </div>
          <!-- 右侧区域 -->
          <div class="right-section">
            <a-tabs v-model:activeKey="activeTab">
              <a-tab-pane key="voiceLib" tab="语音库">
                <div class="voice-library">
                  <a-input-search v-model:value="searchText" :placeholder="searchPlaceholder" class="search-input" />
                  <a-radio-group v-model:value="voiceTitleType" class="voice-type-selector">
                    <a-radio-button value="system" class="voice-type-button">系统声音</a-radio-button>
                    <a-radio-button value="clone" class="voice-type-button">克隆声音</a-radio-button>
                  </a-radio-group>
                  <div class="voice-list">
                    <div class="voice-grid">
                      <div v-for="voice in voices" :key="voice.id" :class="{'selected': selectedVoice === voice.id}"
                        class="voice-card" @click="selectVoice(voice.id)">
                        <div class="voice-card-header">
                          <span class="voice-name">{{ voice.voiceName }}</span>
                          <a-tag :color="voice.voiceType === 'system' ? 'blue' : 'green'">
                            {{ voice.voiceType === 'system' ? '系统' : '克隆' }}
                          </a-tag>
                        </div>
                        <div class="voice-card-footer">
                          <span
                            class="voice-description">{{ voice.voiceType === 'system' ? voice.shortDescription : voice.voiceNote }}</span>
                          <play-circle-outlined v-if="!isPreviewPlaying || currentPreviewId !== voice.id"
                            class="play-icon" @click.stop="playPreviewAudio(voice)" />
                          <pause-circle-outlined v-else class="play-icon" @click.stop="playPreviewAudio(voice)" />
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </a-tab-pane>
              <a-tab-pane key="settings" tab="设置">
                <div class="settings-section">
                  <div class="setting-section">
                    <h3 class="section-title">语音设置</h3>
                    <div class="setting-item">
                      <div class="speed-control">
                        <div class="speed-header">
                          <div class="speed-title">
                            <span class="label">语速</span>
                            <a-tooltip placement="right" title="调整语音播放的速度">
                              <QuestionCircleOutlined class="help-icon" />
                            </a-tooltip>
                          </div>
                          <span class="speed-value">{{ speedValue }}x</span>
                        </div>
                        <a-slider v-model:value="speedValue" :min="0.5" :max="2" :step="0.1" :marks="speedMarks"
                          class="custom-slider" />
                      </div>
                    </div>
                  </div>
                  <div class="setting-section">
                    <h3 class="section-title">输出设置</h3>
                    <div class="setting-item">
                      <span class="setting-label">输出格式</span>
                      <a-select v-model:value="outputFormat" class="setting-select">
                        <a-select-option value="mp3">MP3</a-select-option>
                        <a-select-option value="wav">WAV</a-select-option>
                      </a-select>
                    </div>
                  </div>
                </div>

              </a-tab-pane>
              <a-tab-pane key="history" tab="历史记录">
                <div class="history-section">
                  <div class="history-list">
                    <div v-for="record in historyRecords" :key="record.id" class="history-item">
                      <div class="history-content">
                        <div class="history-text">{{ record.inputText }}</div>
                        <div class="history-info">
                          <span class="history-time">{{ record.createTime }}</span>
                          <span class="history-voice">{{ record.voiceName }}</span>
                        </div>
                      </div>
                      <div class="history-actions">
                        <play-circle-outlined v-if="!isPlaying || currentPlayingId !== record.id"
                          class="history-action-icon" @click="handleHistoryAudioPlay(record)" />
                        <pause-circle-outlined v-else class="history-action-icon"
                          @click="handleHistoryAudioPlay(record)" />
                        <download-outlined class="history-action-icon" @click="handleHistoryDownload(record)" />
                        <!-- 添加 Popconfirm 确认框 -->
                        <a-popconfirm title="确定要删除这条记录吗？" ok-text="确认" cancel-text="取消"
                          @confirm="handleDeleteHistory(record.id)">
                          <template #icon><question-circle-outlined style="color: red" /></template>
                          <delete-outlined class="delete" />
                        </a-popconfirm>
                      </div>
                    </div>
                  </div>
                </div>
              </a-tab-pane>
            </a-tabs>
          </div>
        </div>
        <!-- 底部播放器 -->
        <div class="player">
          <div class="player-container">
            <div class="player-controls">
              <div class="player-status" :class="{
                'generating': isGenerating,
                'completed': audioUrl && !isGenerating,
                'initial': !audioUrl
              }">
                <info-circle-outlined v-if="!audioUrl" class="status-icon info" />
                <loading-outlined v-else-if="isGenerating" class="status-icon loading" />
                <check-circle-outlined v-else class="status-icon success" />
                <span class="status-text" :class="{
                  'initial': !audioUrl,
                  'generating': isGenerating,
                  'completed': audioUrl && !isGenerating
                }">
                  {{ !audioUrl ? '等待生成语音' : (isGenerating ? '生成语音中...' : '生成完成') }}
                </span>
              </div>
              <div class="player-main">
                <play-circle-outlined v-if="!isMainPlaying" class="main-play-icon" @click="toggleMainAudio"
                  :class="{ 'disabled': isGenerating }" />
                <pause-circle-outlined v-else class="main-play-icon" @click="toggleMainAudio"
                  :class="{ 'disabled': isGenerating }" />
                <span class="player-time">{{ currentTime }}/{{ duration }}</span>
                <div class="progress-bar">
                  <a-slider v-model:value="audioProgress" :min="0" :max="100" :disabled="!audioUrl"
                    :tooltip-open="false" @change="handleProgressChange" />
                </div>
              </div>
              <div class="player-actions">
                <a-select v-model:value="speedNumber" style="width: 90px" size="small" class="custom-select">
                  <a-select-option v-for="item in speedDisplay" :key="item.value" :value="item.value">
                    {{ item.label }}
                  </a-select-option>
                </a-select>
                <div class="player-right">
                  <div class="volume-control">
                    <sound-outlined class="volume-icon" />
                    <div class="volume-slider-container">
                      <div class="volume-slider-wrapper">
                        <a-slider v-model:value="volume" :min="0" :max="100" vertical class="volume-slider" />
                      </div>
                    </div>
                  </div>
                  <a-tooltip placement="top">
                    <template #title>
                      下载语音文件
                    </template>
                    <download-outlined class="download-icon" @click="handleMainDownload"
                      :class="{ 'disabled': isGenerating }" />
                  </a-tooltip>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
  import { ref, computed, onMounted, watch, onUnmounted } from 'vue';
  import { message } from 'ant-design-vue';
  import {
    QuestionCircleOutlined,
    SearchOutlined,
    PlayCircleOutlined,
    PauseCircleOutlined,
    UploadOutlined,
    SoundOutlined,
    DownloadOutlined,
    DeleteOutlined,
    CheckCircleOutlined,
    FileTextOutlined
  } from '@ant-design/icons-vue';
  import { getVoiceList } from '@/api/VoiceLibrary';
  import { generateVoice, getHistory, deleteHistory, generateVoiceFromFile, getCloneStatus } from '@/api/TextToSpeech'

  const voices = ref([]);
  const searchText = ref('');
  const voiceTitleType = ref('system');
  const outputFormat = ref('wav');

  // 获取声音列表数据
  const fetchVoiceList = async (type = voiceTitleType.value, keyword = searchText.value) => {
    try {
      const res = await getVoiceList({ type, keyword });
      voices.value = res.data.list;
      console.log(res);

    } catch (error) {
      console.error('获取声音列表失败:', error);
    }
  };
  // 监听搜索关键字和声音类型变化
  watch([searchText, voiceTitleType], async ([newKeyword, newType]) => {
    await fetchVoiceList(newType, newKeyword);
  });
  // 搜索相关
  const searchPlaceholder = computed(() => {
    return voiceTitleType.value === 'system' ? '搜索系统声音' : '搜索自定义声音';
  });
  const previewAudioPlayer = ref(null);
  const isPreviewPlaying = ref(false);
  const currentPreviewId = ref(null);

  // 播放预览音频
  const playPreviewAudio = async (voice) => {
    try {
      console.log(voice);

      if (!voice.outputUrl) {
        message.warning('音频文件不存在',1);
        return;
      }

      // 如果当前正在播放这个音频，切换播放状态
      if (currentPreviewId.value === voice.id) {
        if (isPreviewPlaying.value) {
          previewAudioPlayer.value.pause();
          isPreviewPlaying.value = false;
          currentPreviewId.value = null;
          return;
        }
      } else {
        // 如果要播放新的音频，先停止当前播放
        if (previewAudioPlayer.value) {
          previewAudioPlayer.value.pause();
          isPreviewPlaying.value = false;
          currentPreviewId.value = null;
        }
      }

      // 初始化音频播放器
      if (!previewAudioPlayer.value) {
        previewAudioPlayer.value = new Audio();
        previewAudioPlayer.value.addEventListener('ended', () => {
          isPreviewPlaying.value = false;
          currentPreviewId.value = null;
        });
      }

      // 设置新的音频源并播放
      previewAudioPlayer.value.src = voice.outputUrl;
      await previewAudioPlayer.value.play();

      // 更新播放状态
      isPreviewPlaying.value = true;
      currentPreviewId.value = voice.id;
    } catch (error) {
      console.error('播放预览音频失败:', error);
      message.error('播放音频失败',1);
      isPreviewPlaying.value = false;
      currentPreviewId.value = null;
    }
  };

  // 组件卸载时清理音频播放器
  onUnmounted(() => {
    if (previewAudioPlayer.value) {
      previewAudioPlayer.value.pause();
      previewAudioPlayer.value = null;
    }
  });
  // 在组件挂载时获取数据
  onMounted(async () => {
    await fetchVoiceList();
    //获取历史记录的数据
    const response = await getHistory();
    historyRecords.value = response.data.list;
  });

  // 设置语速模块
  const speedValue = ref(1);
  const speedMarks = {
    2.0: '2.0x',
    1.7: '1.7x',
    1.5: '1.5x',
    1.2: '1.2x',
    1.0: '1.0x',
    0.7: '0.7x',
    0.5: '0.5x'
  };
  // 调节倍速播放的模块
  const speedNumber = ref(1.0)
  const speedDisplay = [
    { value: 2.0, label: '2.0x' },
    { value: 1.5, label: '1.5x' },
    { value: 1.25, label: '1.25x' },
    { value: 1.0, label: '1.0x' },
    { value: 0.75, label: '0.75x' },
    { value: 0.5, label: '0.5x' }
  ];



  const activeTab = ref('voiceLib');
  const selectedVoice = ref('');
  // 选择声音
  const selectVoice = (id) => {
    selectedVoice.value = id;
  };

  // 计算属性：判断是否可以生成语音
  const canGenerate = computed(() => {
    if (inputType.value === 'text') {
      return inputText.value.trim() !== '';
    } else {
      return uploadedFile.value !== null;
    }
  });
  const inputType = ref('text');
  const inputText = ref('');
  const fileInput = ref(null);
  const uploadedFile = ref(null);
  const maxFileSize = 10 * 1024 * 1024; // 10MB

  //设置输入类型
  const setInputType = (type) => {
    inputType.value = type;
    // 切换输入类型时重置相关状态
    if (type === 'text') {
      uploadedFile.value = null;
    } else {
      inputText.value = '';
    }
  };
  // 处理文件点击
  const handleFileClick = () => {
    if (!isGenerating.value) {
      fileInput.value.click();
    }
  };

  // 处理文件选择
  const handleFileSelect = (event) => {
    if (!isGenerating.value) {
      const file = event.target.files[0];
      if (file) {
        validateAndSetFile(file);
      }
    }
  };
  // 格式化文件大小的函数
  const formatFileSize = (bytes) => {
    if (bytes === 0) return '0 B';
    const units = ['B', 'KB', 'MB', 'GB'];
    const k = 1024;
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return `${(bytes / Math.pow(k, i)).toFixed(1)} ${units[i]}`;
  };
  // 处理文件拖放
  const handleFileDrop = (event) => {
    if (!isGenerating.value) {
      const file = event.dataTransfer.files[0];
      if (file) {
        validateAndSetFile(file);
      }
    }
  };

  // 验证并设置文件
  const validateAndSetFile = (file) => {
    const validTypes = ['.txt'];
    const fileExtension = '.' + file.name.split('.').pop().toLowerCase();

    if (!validTypes.includes(fileExtension)) {
      message.error('不支持的文件格式',1);
      return;
    }

    if (file.size > maxFileSize) {
      message.error('文件大小不能超过10MB',1);
      return;
    }

    uploadedFile.value = file;
  };
  //生成语音方法
  const handleGenerate = async () => {
    if (inputType.value === 'text' && !inputText.value.trim()) return;
    if (inputType.value === 'file' && !uploadedFile.value) return;
    if (!selectedVoice.value) {
      message.warning('请选择音色',1);
      return;
    }

    isGenerating.value = true;
    message.loading('正在生成音频，请稍候...', 0);
    try {
      let voiceData;
      let recordId;
      if (inputType.value === 'text') {
        voiceData = {
          text: inputText.value,
          id: selectedVoice.value,
          speed: speedValue.value,
          pitch: 1,
          format: outputFormat.value
        };
        const res = await generateVoice(voiceData);
        recordId = res.data.recordId;
      } else {
        const formData = new FormData();
        // const data = {
        //   id: selectedVoice.value,
        //   speed: speedValue.value,
        //   pitch: 1,
        //   format: outputFormat.value
        // };
        // const dataBlob = new Blob([JSON.stringify(data)], { type: 'application/json' });
        // formData.append('data', dataBlob);
        // 正确方式：每个参数单独添加
        formData.append('id', selectedVoice.value);
        formData.append('speed', speedValue.value);
        formData.append('pitch', '1'); // 确保类型正确（字符串）
        formData.append('format', outputFormat.value);
        formData.append('file', uploadedFile.value);
        const res = await generateVoiceFromFile(formData);
        recordId = res.data.recordId;

      }

      let retryCount = 0;
      const maxRetries = 60; // 最大轮询次数，约2分钟
      const pollingInterval = 2000; // 轮询间隔2秒

      // 轮询检查生成进度
      const checkProgress = async () => {
        try {
          if (retryCount >= maxRetries) {
            message.destroy();
            message.error('生成音频超时，请重试',1);
            isGenerating.value = false;
            return;
          }
          // 获取生成进度的状态
          const statusRes = await getCloneStatus(recordId);
          const progress = statusRes.data.progress;
          if (progress < 100) {
            retryCount++;
            // 使用setTimeout代替直接调用，增加轮询间隔
            setTimeout(checkProgress, pollingInterval);
          } else {
            fetchHistory(recordId);
          }
        } catch (error) {
          console.error('检查生成进度失败:', error);
          message.destroy();
          message.error('生成音频失败，请重试',1);
          isGenerating.value = false;
        }
      };
      // 开始检查进度
      checkProgress();
    } catch (error) {
      console.error('生成语音失败:', error);
      message.destroy();
      message.error('生成音频失败，请重试',1);
      isGenerating.value = false;
    }
  };

  // 获取新的历史记录
  const fetchHistory = async (recordId) => {
    try {
      const res = await getHistory();
      console.log(res);
      // 从列表中找到对应recordId的音频数据
      const audioData = res.data.list.find(item => item.id === recordId);

      historyRecords.value = res.data.list;
      if (audioData) {
        audioUrl.value = audioData.audioUrl;
        console.log(audioUrl.value);
        // 初始化音频播放器并设置音频源
        audioPlayerUtil.setAudioSource(audioUrl.value);
        isGenerating.value = false;
        message.destroy(); // 清除loading提示
        message.success('音频生成完成');
      } else {
        message.error('未找到对应的音频数据');
      }
      historyRecords.value = res.data.list;
    } catch (error) {
      console.error('获取历史记录失败:', error);
    }
  };

  // 历史记录模块
  const audioPlayer = ref(null);
  const isPlaying = ref(false);
  const currentPlayingId = ref(null);
  // 组件卸载时清理音频播放器
  onUnmounted(() => {
    if (audioPlayer.value) {
      audioPlayer.value.pause();
      audioPlayer.value = null;
    }
  });
  // 历史记录数据
  const historyRecords = ref([]);

  // 删除历史记录
  const handleDeleteHistory = async (id) => {
    try {
      await deleteHistory(id);
      message.success('删除成功',1);
      //重新获取历史记录的数据
      const response = await getHistory();
      historyRecords.value = response.data.list;
    } catch (error) {
      console.error('删除历史记录失败:', error);
    }
  };

  // 处理历史记录音频播放
  const handleHistoryAudioPlay = async (record) => {
    try {
      if (!record.audioUrl) {
        message.warning('音频文件不存在',1);
        return;
      }

      if (!audioPlayer.value) {
        audioPlayer.value = new Audio();
        audioPlayer.value.addEventListener('ended', () => {
          isPlaying.value = false;
          currentPlayingId.value = null;
        });
      }

      // 如果当前正在播放这个音频，切换播放/暂停状态
      if (currentPlayingId.value === record.id) {
        if (isPlaying.value) {
          audioPlayer.value.pause();
          isPlaying.value = false;
          currentPlayingId.value = null;
        } else {
          try {
            audioPlayer.value.src = record.audioUrl;
            await audioPlayer.value.play();
            isPlaying.value = true;
            currentPlayingId.value = record.id;
          } catch (error) {
            isPlaying.value = false;
            currentPlayingId.value = null;
            message.error('音频播放失败',1);
          }
        }
        return;
      }

      // 如果正在播放其他音频，先停止
      if (isPlaying.value) {
        audioPlayer.value.pause();
        isPlaying.value = false;
        currentPlayingId.value = null;
      }

      // 播放新的音频
      try {
        audioPlayer.value.src = record.audioUrl;
        await audioPlayer.value.play();
        isPlaying.value = true;
        currentPlayingId.value = record.id;
      } catch (error) {
        isPlaying.value = false;
        currentPlayingId.value = null;
        message.error('音频播放失败',1);
      }
    } catch (error) {
      console.error('音频播放失败:', error);
      isPlaying.value = false;
      currentPlayingId.value = null;
      message.error('音频播放失败',1);
    }
  };

  // 处理历史记录音频下载
  const handleHistoryDownload = (record) => {
    if (!record.audioUrl) {
      message.warning('音频文件不存在',1);
      return;
    }
    const link = document.createElement('a');
    link.href = record.audioUrl;
    link.download = `audio_${record.id}.${outputFormat.value}`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };
  // 导入音频播放器工具类
  import audioPlayerUtil from '@/utils/audioPlayer';
  // 底部播放器模块
  const audioProgress = ref(0);
  const isGenerating = ref(false);
  const audioUrl = ref('');
  const volume = ref(50);
  const duration = ref('00:00');
  const currentTime = ref('00:00');
  const isMainPlaying = ref(false);

  // 监听audioUrl变化，初始化音频播放器
  watch(audioUrl, (newUrl) => {
    if (newUrl) {
      audioPlayerUtil.setAudioSource(newUrl);
      isGenerating.value = false;
      // message.success('音频生成完成');

      // 监听音频播放进度和时间更新
      audioPlayerUtil.audio.addEventListener('timeupdate', () => {
        currentTime.value = audioPlayerUtil.currentTime;
        duration.value = audioPlayerUtil.duration;
        audioProgress.value = audioPlayerUtil.audioProgress;
      });

      // 监听音频加载完成事件
      audioPlayerUtil.audio.addEventListener('loadedmetadata', () => {
        duration.value = audioPlayerUtil.formatTime(audioPlayerUtil.audio.duration);
      });
    }
  });

  // 监听音量变化
  watch(volume, (newVolume) => {
    audioPlayerUtil.setVolume(newVolume);
  });

  // 监听播放速度变化
  watch(speedNumber, (newSpeed) => {
    audioPlayerUtil.setPlaybackRate(newSpeed);
  });

  // 节流函数
  const throttle = (fn, delay) => {
    let lastTime = 0;
    let rafId = null;
    return function (...args) {
      const now = Date.now();
      if (now - lastTime >= delay) {
        if (rafId) {
          cancelAnimationFrame(rafId);
        }
        rafId = requestAnimationFrame(() => {
          fn.apply(this, args);
          lastTime = now;
          rafId = null;
        });
      }
    };
  };

  // 更新播放进度和时间
  const updatePlaybackInfo = () => {
    if (audioPlayerUtil.audio) {
      audioProgress.value = audioPlayerUtil.audioProgress;
      currentTime.value = audioPlayerUtil.currentTime;
      duration.value = audioPlayerUtil.duration;
    }
  };

  // 节流后的更新函数
  const throttledUpdatePlaybackInfo = throttle(updatePlaybackInfo, 50);

  // 处理进度条变化
  const handleProgressChange = (value) => {
    if (audioPlayerUtil.audio) {
      const duration = audioPlayerUtil.audio.duration;
      const newTime = (value / 100) * duration;
      audioPlayerUtil.audio.currentTime = newTime;
      currentTime.value = audioPlayerUtil.formatTime(newTime);
      audioProgress.value = value;
    }
  };

  onMounted(() => {
    if (audioPlayerUtil.audio) {
      audioPlayerUtil.audio.addEventListener('timeupdate', throttledUpdatePlaybackInfo);
    }
  });

  onUnmounted(() => {
    if (audioPlayerUtil.audio) {
      audioPlayerUtil.audio.removeEventListener('timeupdate', throttledUpdatePlaybackInfo);
    }
    audioPlayerUtil.destroy();
  });

  // 处理主播放器下载
  const handleMainDownload = () => {
    if (!audioUrl.value) {
      message.warning('暂无可下载的音频',1);
      return;
    }
    if (isGenerating.value) {
      message.warning('正在生成音频，无法播放',1);
      return;
    }
    const link = document.createElement('a');
    link.href = audioUrl.value;
    link.download = `audio_${Date.now()}.${outputFormat.value}`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };




  // 切换播放/暂停状态
  const toggleMainAudio = async () => {
    if (!audioUrl.value) {
      message.warning('暂无可播放的音频',1);
      return;
    }
    if (isGenerating.value) {
      message.warning('正在生成音频，无法播放',1);
      return;
    }
    try {
      if (isMainPlaying.value) {
        audioPlayerUtil.pause();
        isMainPlaying.value = false;
      } else {
        await audioPlayerUtil.play();
        isMainPlaying.value = true;
      }
    } catch (error) {
      message.error('音频播放失败',1);
      isMainPlaying.value = false;
    }
  };

  // 监听进度变化
  watch(() => audioProgress.value, (newProgress) => {
    if (newProgress === 100) {
      isMainPlaying.value = false;
      currentTime.value = '00:00';
      audioProgress.value = 0;
    }
  });

</script>

<style lang="scss" scoped>
  .tts-container {

    background-color: #f3f4f6;

    .container {
      max-width: 90rem;
      height: 90.1vh;
      margin: 0 auto;
      padding: 0.7rem 1.5rem;

      .content {
        display: flex;
        flex-direction: column;
        min-height: calc(100vh - 7.5rem);

        .main-content {
          flex: 1;
          display: flex;
          gap: 1.5rem;
          height: 60%;

          .left-section {
            width: 66%;
            height: 100%;
            margin-top: 13px;

            .header {
              margin-bottom: 1.5rem;
              display: flex;
              align-items: center;
              justify-content: space-between;

              .title {
                font-size: 1.5rem;
                font-weight: 500;
              }

              .help-icon {
                font-size: 1.25rem;
                color: #9ca3af;
                cursor: pointer;

                &:hover {
                  color: #3b82f6;
                }
              }
            }

            .input-section {
              height: 700px;
              background-color: white;
              border-radius: 0.5rem;
              box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
              padding: 1rem;

              .input-type-buttons {
                display: flex;
                gap: 1rem;
                margin-bottom: 1rem;

                .input-button {
                  border-radius: 0.375rem;

                  &.active {
                    background-color: #3b82f6;
                    color: white;
                  }
                }
              }

              .text-input-wrapper {
                position: relative;
                height: calc((100vh - 16rem) * 0.75);

                .text-area {
                  resize: none;
                  border-radius: 0.5rem;
                  height: 100%;
                  font-size: 1rem;
                }

                .text-counter {
                  position: relative;
                  margin-top: 0.5rem;
                  margin-left: 0.5rem;
                  font-size: 0.875rem;
                  color: #9ca3af;
                }
              }

              .file-upload-section {
                border: 2px dashed #e5e7eb;
                border-radius: 0.5rem;
                padding: 2rem;
                text-align: center;
                height: calc((100vh - 16rem) * 0.75);
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                transition: all 0.3s;

                .upload-icon {
                  font-size: 2.25rem;
                  color: #d1d5db;
                  margin-bottom: 0.5rem;
                }

                .upload-text {
                  color: #6b7280;
                }

                .upload-hint {
                  color: #9ca3af;
                  font-size: 0.875rem;
                }

                &:hover {
                  border-color: #60a5fa;
                  border-style: dashed;
                  background-color: rgba(96, 165, 250, 0.05);
                }
              }
            }

            .generate-button-wrapper {
              display: flex;
              justify-content: flex-end;
              /* margin-bottom: 15rem; */
              margin-top: 30px;
            }

            .generate-button {
              border-radius: 0.25rem;
              white-space: nowrap;
              border: none;
              transform: scale(1.3);
              transform-origin: center;
              margin: 0 1.2rem;
              padding: 0.4rem 1.5rem;
            }

            .disabled-button {
              opacity: 0.5;
              cursor: not-allowed;
              background-color: #f6f5f7;
            }

          }

          .right-section {
            width: 34%;
            height: 100%;
            /* height: calc((100vh - 16rem) * 0.8); */
            overflow-y: auto;

            :deep(.ant-tabs-nav) {
              margin-bottom: 0;

              .ant-tabs-nav-list {
                width: 100%;
                display: flex;
                justify-content: space-between;

                .ant-tabs-tab {
                  flex: 1;
                  text-align: center;
                  padding: 8px 0;
                  margin: 0;
                  display: flex;
                  justify-content: center;
                  align-items: center;

                  .ant-tabs-tab-btn {
                    padding: 0;
                  }
                }

                .ant-tabs-tab-active {
                  .ant-tabs-tab-btn {
                    color: #2563eb;
                  }
                }

                .ant-tabs-ink-bar {
                  bottom: 0;
                  width: 33.33% !important;
                }
              }

              .ant-tabs-nav-operations {
                display: none !important;
              }
            }

            .voice-library {
              margin-top: 23px;
              height: 650px;
              background-color: white;
              border-radius: 0.5rem;
              box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
              padding: 1rem;

              .search-input {
                margin-bottom: 1rem;

                .search-icon {
                  color: #9ca3af;
                }
              }

              .voice-type-selector {
                margin-bottom: 1rem;
                width: 100%;
                border: 1px solid #e5e7eb;
                border-radius: 0.5rem;

                .voice-type-button {
                  width: 50%;
                  text-align: center;
                }
              }

              .voice-list {
                height: 520px;
                overflow-y: auto;
                padding-right: 0.5rem;

                /* 自定义滚动条样式 */
                &::-webkit-scrollbar {
                  width: 6px;
                }

                &::-webkit-scrollbar-track {
                  background: #e5e5e5;
                  border-radius: 3px;
                }

                &::-webkit-scrollbar-thumb {
                  background: #e5e5e5;
                  border-radius: 3px;

                  &:hover {
                    background: #b2b2b2;
                  }
                }

                .voice-grid {
                  display: grid;
                  grid-template-columns: repeat(2, 1fr);
                  gap: 1rem;

                  /* 自定义滚动条样式 */
                  &::-webkit-scrollbar {
                    width: 6px;

                  }

                  &::-webkit-scrollbar-track {
                    background: #e5e5e5;
                    border-radius: 3px;
                  }

                  &::-webkit-scrollbar-thumb {
                    background: #e5e5e5;
                    border-radius: 3px;

                    &:hover {
                      background: #b2b2b2;
                    }
                  }

                  .voice-card {
                    background-color: white;
                    border-radius: 0.5rem;
                    padding: 0.75rem 0 0.75rem 0.5rem;
                    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
                    display: flex;
                    flex-direction: column;
                    border: 2px solid #e5e7eb;
                    transition: border-color 0.3s ease;

                    &:hover {
                      border-color: #4897f8;
                    }

                    &.selected {
                      border-color: #4897f8;
                    }

                    .voice-card-header {

                      display: flex;
                      align-items: center;
                      justify-content: space-between;
                      margin-bottom: 0.5rem;

                      .voice-name {
                        font-weight: 500;
                        color: #1f2937;
                      }
                    }

                    .voice-card-footer {
                      display: flex;
                      align-items: center;
                      justify-content: space-between;

                      .voice-description {
                        color: #6b7280;
                        font-size: 0.875rem;
                      }

                      .play-icon {
                        margin-right: 15px;
                        color: #2563eb;
                        font-size: 1.25rem;
                        cursor: pointer;

                        &:hover {
                          color: #1d4ed8;
                        }
                      }
                    }
                  }
                }
              }
            }

            /* 设置部分样式 */
            .settings-section {
              margin-top: 23px;
              height: 650px;
              background-color: white;
              border-radius: 0.5rem;
              box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
              padding: 1rem;

              .setting-section {
                margin-bottom: 1.5rem;
                padding: 1rem;
                border-radius: 0.5rem;

                .section-title {
                  font-size: 1rem;
                  font-weight: 500;
                  color: #1f2937;
                  margin-bottom: 1rem;
                }
              }

              .setting-item {
                display: flex;
                align-items: center;
                margin-bottom: 1rem;

                &:last-child {
                  margin-bottom: 0;
                }

                .speed-control {
                  display: flex;
                  flex-direction: column;
                  gap: 1rem;
                  width: 100%;

                  .speed-header {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    margin-bottom: 0.5rem;
                  }

                  .speed-title {
                    display: flex;
                    align-items: center;
                    gap: 0.5rem;
                  }

                  .speed-value {
                    color: #6b7280;
                  }

                }

                .custom-slider {
                  margin-left: 15px;
                  width: 90%;

                  :deep(.ant-slider-track) {
                    background: linear-gradient(90deg, #4f83f1 0%, #2563eb 100%);
                  }

                  :deep(.ant-slider-mark-text) {
                    color: #666;
                    font-size: 12px;
                  }

                  :deep(.ant-slider-mark-text-active) {
                    color: #2563eb;
                  }

                  :deep(.ant-slider-handle) {
                    border-color: #2563eb;

                    &:hover {
                      border-color: #2563eb;
                    }
                  }
                }

                .setting-label {
                  margin-right: 8px;
                }

                .setting-select {
                  flex: 1;
                }
              }
            }

            /* 历史部分样式 */
            .history-section {
              margin-top: 23px;
              height: 650px;
              background-color: white;
              border-radius: 0.5rem;
              box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
              padding: 1rem 0.35rem 1rem 1rem;

              .history-list {
                display: flex;
                flex-direction: column;
                gap: 0.75rem;
                height: 620px;
                overflow-y: auto;
                padding-right: 8px;

                /* 自定义滚动条样式 */
                &::-webkit-scrollbar {
                  width: 6px;
                }

                &::-webkit-scrollbar-track {
                  background: #e5e5e5;
                  border-radius: 3px;
                }

                &::-webkit-scrollbar-thumb {
                  background: #e5e5e5;
                  border-radius: 3px;

                  &:hover {
                    background: #b2b2b2;
                  }
                }

                .history-item {
                  background-color: #f9fafb;
                  border-radius: 0.5rem;
                  padding: 1rem;
                  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
                  display: flex;
                  justify-content: space-between;
                  align-items: center;
                  border: 1.5px solid transparent;
                  transition: border-color 0.3s ease;

                  &:hover {
                    border-color: #2563eb;
                  }

                  .history-content {
                    flex: 1;
                    min-width: 0;

                    .history-text {
                      font-size: 0.875rem;
                      color: #1f2937;
                      margin-bottom: 0.5rem;
                      white-space: nowrap;
                      overflow: hidden;
                      text-overflow: ellipsis;
                    }

                    .history-info {
                      display: flex;
                      gap: 1rem;
                      font-size: 0.75rem;
                      color: #6b7280;

                      .history-time {
                        white-space: nowrap;
                      }

                      .history-voice {
                        white-space: nowrap;
                      }
                    }
                  }

                  .history-actions {
                    display: flex;
                    gap: 0.75rem;
                    margin-left: 1rem;

                    .history-action-icon {
                      font-size: 1.125rem;
                      color: #6b7280;
                      cursor: pointer;

                      &:hover {
                        color: #2563eb;
                      }
                    }

                    .delete {
                      font-size: 1.125rem;
                      color: #6b7280;
                      cursor: pointer;

                      &:hover {
                        color: #f5222d;
                      }
                    }
                  }
                }
              }


            }
          }
        }

        /* 底部样式 */
        .player {

          background-color: white;
          border-top: 1px solid #e5e7eb;
          padding: 1rem;

          .player-container {
            margin: 0 auto;

            .player-controls {
              display: flex;
              align-items: center;
              gap: 6rem;

              .player-status {
                display: flex;
                align-items: center;
                padding: 4px 12px;
                margin-left: 60px;
                border-radius: 4px;
                transition: all 0.3s ease;
                background-color: #f5f5f5;
                border: 1px solid #d9d9d9;
                white-space: nowrap;


                &.generating {
                  background-color: #e6f4ff;
                  border-color: #0b59d9;

                  .loading {
                    animation: spin 1s linear infinite;
                  }
                }

                &.completed {
                  background-color: #f6ffed;
                  border-color: #27c461;
                }

                .status-icon {
                  font-size: 16px;
                  margin-right: 8px;

                  &.info {
                    color: #595959;
                  }

                  &.loading {
                    color: #0e5bda;
                  }

                  &.success {
                    color: #52c41a;
                  }
                }

                .status-text {
                  font-size: 14px;
                  line-height: 1;

                  &.initial {
                    color: #595959;
                  }

                  &.generating {
                    color: #0e5bda;
                  }

                  &.completed {
                    color: #52c41a;
                  }
                }
              }

              .player-main {
                display: flex;
                align-items: center;
                gap: 1rem;

                .main-play-icon {
                  font-size: 1.75rem;
                  cursor: pointer;

                  &:hover {
                    color: #3b82f6;
                  }

                  &.disabled {
                    color: #9ca3af;

                    &:hover {
                      color: #9ca3af;
                    }
                  }
                }

                .player-time {
                  color: #6b7280;
                  font-size: 0.875rem;
                }

                .progress-bar {
                  width: 700px;
                  flex: 1;

                }
              }

              .player-actions {
                display: flex;
                gap: 1rem;

                .custom-select {
                  margin-right: 15px;
                }

                .player-right {
                  position: relative;
                  display: flex;
                  align-items: center;
                  gap: 1rem;
                }

                /* 音量控制 */
                .volume-control {
                  &:hover .volume-slider-container {
                    opacity: 1;
                    visibility: visible;
                    transform: translateY(0);
                  }
                }

                .volume-icon {
                  font-size: 1.125rem;
                  cursor: pointer;

                  &:hover {
                    color: #2563eb;
                  }
                }

                .volume-slider-container {
                  position: absolute;
                  bottom: calc(100% + 0.7rem);
                  /* left: 50%; */
                  /* transform: translateX(-50%) translateY(10px); */
                  right: 35%;
                  opacity: 0;
                  visibility: hidden;
                  transition: all 0.3s ease;
                  z-index: 20;
                }

                .volume-slider-wrapper {
                  background-color: white;
                  padding: 0.75rem 0.5rem;
                  border-radius: 0.5rem;
                  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
                  position: relative;

                  &::after {
                    content: '';
                    position: absolute;
                    bottom: -6px;
                    left: 50%;
                    transform: translateX(-50%) rotate(45deg);
                    width: 12px;
                    height: 12px;
                    background-color: white;
                    box-shadow: 4px 4px 15px rgba(0, 0, 0, 0.1);
                  }
                }

                .volume-slider {
                  height: 6rem;
                }

                .download-icon {
                  font-size: 1.125rem;
                  cursor: pointer;
                  margin-bottom: .0875rem;

                  &:hover {
                    color: #2563eb;
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  .file-upload-section {
    border: 2px dashed #d9d9d9;
    border-radius: 8px;
    padding: 20px;
    text-align: center;
    cursor: pointer;
    margin-bottom: 20px;
    transition: all 0.3s;
  }

  .file-upload-section:hover:not(.disabled) {
    border-color: #1890ff;
  }

  .file-upload-section.disabled {
    cursor: not-allowed;
    background-color: #f5f5f5;
    opacity: 0.7;
  }

  .uploaded-file-info {
    margin-top: 16px;
    padding: 16px;
    background-color: #f6f6f6;
    border-radius: 8px;
    transition: all 0.3s ease;
  }

  .file-info-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
  }

  .file-icon {
    font-size: 24px;
    color: #1890ff;
  }

  .file-name {
    color: #333;
    font-size: 16px;
    font-weight: 500;
    word-break: break-all;
    line-height: 1.4;
  }

  .file-details {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-left: 36px;
  }

  .file-size {
    color: #666;
    font-size: 14px;
  }

  .uploaded-file-info:hover {
    background-color: #f0f0f0;
    transform: translateY(-2px);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }
</style>